package fox.framework.rpc.client;


import fox.framework.rpc.client.message.RpcClientRequestInterceptor;
import fox.framework.rpc.client.node.rule.RuleFactory;
import fox.framework.rpc.common.StringUtils;
import fox.framework.rpc.context.definition.RpcDefinition;
import fox.framework.rpc.converter.RpcMessageConverter;
import fox.framework.rpc.converter.RpcMessageConverters;
import fox.framework.rpc.endpoint.RpcEndPoint;

import java.util.ArrayList;
import java.util.List;


/**
 * @author cuichao
 * @Description: ConfigurableRpcClient
 * @Date: create in 2021/1/5 15:26
 */
public abstract class ConfigurableRpcClient implements RpcClient, Registrable {

    public ConfigurableRpcClient(String bind, int port) {
        this.bind = bind;
        this.port = port;
    }
    /**
     * 绑定的IP地址
     */
    private String bind;
    /**
     * 监听端口
     */
    private int port;
    /**
     * 本机地址
     */
    private String address;
    /**
     * 全局protocol
     */
    private String protocol;
    /**
     * rpc终端
     */
    private RpcEndPoint endpoint;
    /**
     * Rpc注册器
     */
    private RpcRegister register;

    /**
     * Rpc节点选择器
     */
    private RuleFactory ruleFactory;
    /**
     * 默认消息转换器
     */
    private RpcMessageConverter defaultConverter;
    /**
     * 数据转换器
     */
    private RpcMessageConverters converters;
    /**
     * Rpc服务注册列表
     */
    private List<RpcDefinition> definitions;
    /**
     * context传入的客户端请求拦截器
     */
    private List<RpcClientRequestInterceptor> unRegisteredInterceptors = new ArrayList<>();



    public String getAddress(){
        if(StringUtils.isEmpty(this.address)){
            address = this.bind+":"+this.port;
        }
        return address;
    }

    public void refreshRpcRequestInterceptor(List<RpcClientRequestInterceptor> interceptor){
        unRegisteredInterceptors.clear();
        unRegisteredInterceptors.addAll(interceptor);
    }


    protected List<RpcClientRequestInterceptor> getUnRegisteredInterceptors(){
        return unRegisteredInterceptors;
    }


    /**
     * 从数据中心获取Rpc节点数据
     * @param metaspace
     */
    @Override
    public void fetchNodes(List<String> metaspace) {
       register.fetch(metaspace);
    }

    /**
     * 启动Rpc终端
     * @throws fox.framework.rpc.exception.RpcException
     */
    protected void enableEndPoint()throws Exception{
        endpoint.publish();
    }

    /**
     * 启动注册器
     * @throws Exception
     */
    protected void enableRegister() throws Exception {
        if(register instanceof AbstractRpcRegister){
            ((AbstractRpcRegister) register).setRegistrable(this);
        }
        register.run();
    }

    /**
     * 注册本地服务
     * @param localMetaspaces
     */
    protected void registerProviders(List<String> localMetaspaces) throws Exception {
        register.register(getAddress(),localMetaspaces);
    }


    protected String getDefaultProtocol(){
        return this.protocol;
    }

    protected RuleFactory getDefaultRuleFactory(){
        return this.ruleFactory;
    }

    protected RpcRegister getRegister(){
        return register;
    }

    protected RpcEndPoint getEndpoint() { return endpoint; }

    protected RpcMessageConverters getMessageConverters(){
        return converters;
    }

    protected RpcMessageConverter getDefaultConverter(){
        return defaultConverter;
    }

    protected List<RpcDefinition> getDefinitions(){ return definitions; }

    public void setGlobalRpcProtocol(String protocol){
        this.protocol = protocol;
    }

    public void setRpcRegister(RpcRegister register){
        this.register = register;
    }

    public void setEndpoint(RpcEndPoint endpoint){ this.endpoint = endpoint;}

    public void setDefaultRuleFactory(RuleFactory ruleFactory){
        this.ruleFactory = ruleFactory;
    }

    public void setMessageConverters(RpcMessageConverters converters){
        this.converters = converters;
    }

    public void setDefaultConverter(RpcMessageConverter defaultConverter){
        this.defaultConverter = defaultConverter;
    }

    public void setRpcDefinitions(List<RpcDefinition> definitions) {
        this.definitions = definitions;
    }
}
